#ifndef TIMER_H_
#define TIMER_H_
#include <time.h>
#include <sys/cdefs.h>
#include <cstdio>

#include "memory_cpp.hpp"
#include "list_cpp.hpp"
/* Temporary disable timer support*/
template <typename... Fs>
struct timer_entry_tmpl {
  const char *name;
  long long value[sizeof...(Fs)];
  long long ncalls;
  static esmd::list<timer_entry_tmpl*> all;

  timer_entry_tmpl(const char *name) {
    this->name = name;
    for (int i = 0; i < sizeof...(Fs); i++) {
      value[i] = 0;
    }
    ncalls = 0;
    all.append(this);
  };
  __always_inline void start() {
    long long cur_value[sizeof...(Fs)] = {Fs::get_count()...};
    for (int i = 0; i < sizeof...(Fs); i++) {
      value[i] -= cur_value[i];
    }
    ncalls ++;
  }
  __always_inline void stop() {
    long long cur_value[sizeof...(Fs)] = {Fs::get_count()...};
    for (int i = 0; i < sizeof...(Fs); i++) {
      value[i] += cur_value[i];
    }
  }
};

struct field_usecs {
  __always_inline static long long get_count() {
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
  }
  static constexpr const char *fmt = "%16lld";
  static constexpr const char *name = "#usecs";
};
struct field_ticks {
  __always_inline static long long get_count() {
    long val;
#if defined(SW2) || defined(__sw_64__)
    asm volatile("rtc %0\n"
                 : "=r"(val));
#elif defined(__x86_64__)
    // asm volatile("rdtsc": "=A"(val));
    unsigned int __a, __d;
    asm volatile("rdtsc"
                 : "=a"(__a), "=d"(__d));
    (val) = ((unsigned long)__a) | (((unsigned long)__d) << 32);
#else
#warning "No ticks implementation on current architecture, consider adding corresponding instructions."
    val = 0;
#endif
    return val;
  }
  static constexpr const char *fmt = "%16lld";
  static constexpr const char *name = "#ticks";
};
template<typename... Fs>
__attribute__((init_priority(102)))
esmd::list<timer_entry_tmpl<Fs...>*> timer_entry_tmpl<Fs...>::all("timers");
using timer_entry = timer_entry_tmpl<
#if defined(SW2) || defined(__sw_64__) || defined(__x86_64__)
  field_ticks,
#endif
  field_usecs>;

void timer_fprint(FILE *f=stdout);
#define DEF_TIMER(x, y) __attribute__((init_priority(103))) timer_entry x(y);
#define timer_start(x) x.start()
#define timer_stop(x) x.stop()
#define timer_init()
#define timer_update(x, y, z)
#define timer_print() timer_fprint()

#endif